package com.api.syh56.shengyunhui.controller;

import com.api.syh56.shengyunhui.common.*;
import com.api.syh56.shengyunhui.entity.*;
import com.api.syh56.shengyunhui.entity.dto.QuoteDTO;
import com.api.syh56.shengyunhui.entity.vo.WAGParamVO;
import com.api.syh56.shengyunhui.entity.vo.WAGParamVOAndQuote;
import com.api.syh56.shengyunhui.exception.BaseException;
import com.api.syh56.shengyunhui.service.*;

import com.api.syh56.shengyunhui.util.CommonUtil;
import com.api.syh56.shengyunhui.websocket.ChatServer;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

import static com.api.syh56.shengyunhui.util.CommonUtil.getLongFromRequestBody;


/**
 * 报价
 */
@RestController
@RequestMapping("quote")
@Slf4j
public class QuoteController {

    @Autowired
    QuoteService quoteService;

    @Autowired
    WayBillService wayBillService;

    @Autowired
    private SystemMessageService systemMessageService;

    @Autowired
    WechatPayService wechatPayService;

    @Autowired
    NotifyService notifyService;

    @Autowired
    UserService userService;

    @Autowired
    private CouponDetService couponDetService;

    @Autowired
    private WaybillRouteService waybillRouteService;

    @Autowired
    private ChatServer chatServer;

    private final ReentrantLock lock = new ReentrantLock();

    /**
     * 司机报价（请求参数waybillId、offerPrice）
     * @param quoteDTO
     * @return
     */
    @PostMapping("driver/waybillQuote")
    public CommonResult<Object> driverWaybillQuote(@RequestBody QuoteDTO quoteDTO){
        Quote quote = quoteDTO.getQuote();
        BigDecimal offerPrice = quote.getOfferPrice();

        if (Objects.isNull(offerPrice) || offerPrice.compareTo(BigDecimal.ZERO) <= 0){
            return CommonResult.failed("报价不允许为负数或空");
        }

        //获取当前司机用户的id
        Long driverId = Long.valueOf(BaseUserInfo.get(UserInfoEnu.id.getCode()));
        //目标订单id
        Long waybillId = quote.getWaybillId();

        Waybill wayBill = wayBillService.getById(waybillId);
        short waybillStatus = wayBill.getWaybillStatus();
        if (!Constants.WaybillStatus.AWAIT_QUOTE.equals(waybillStatus)) {
            throw new BaseException("该订单已被其他专线接单");
        }
        User user = userService.getById(driverId);

        //判断当前司机是否已对该订单完成报价
        QueryWrapper<Quote> quoteQueryWrapper = new QueryWrapper<>();
        quoteQueryWrapper.lambda()
                .eq(Quote::getWaybillId,quote.getWaybillId())
                .eq(Quote::getDriverId,driverId);
        List<Quote> quoteList = quoteService.list(quoteQueryWrapper);
        //当前司机暂未对该订单报价
        if(quoteList.isEmpty()){
            Waybill waybill = wayBillService.selectById(waybillId);
            //报价保存当前货主id和司机id
            quote.setShiperId(waybill.getShiperId());
            quote.setDriverId(driverId);
            //报价状态 进行中
            quote.setStatus(Constants.QuoteStatus.IN_PROGRESS);
            //预计送达天数
            quote.setExpectedDeliveryDays(quoteDTO.getExpectedDay());

            BigDecimal quoteOfferPrice = quote.getOfferPrice();
            //计算平台服务费5%
            quote.setOfferInit(CommonUtil.getPlatformServiceFee(quoteOfferPrice));
            //开票总金额（含税）= 运费 + 平台服务费
            quote.setOfferAll(quote.getOfferPrice().add(quote.getOfferInit()));
            /**
             * todo
             */
            quote.setActAmount(quote.getOfferAll());

            //预计送达时间
            LocalDateTime expectedDeliveryTime = LocalDateTime.now().plusDays(quoteDTO.getExpectedDay());
            quote.setExpectedDeliveryTime(expectedDeliveryTime);

            CommonUtil.setIdToNull(quote);
            quoteService.save(quote);
            //waybill报价数量+1
            waybill.setOfferCount(waybill.getOfferCount()+1);
            //专线地址
            waybill.setDriverLocation(user.getDriverLocation());
            //更改状态

            wayBillService.updateById(waybill);

            /**
             * 司机报价后发送消息给货主
             */
            systemMessageService.SendMessageToShiperWhenDriverQuote(wayBillService.getById(waybillId),quote);
            //修改运单匹配专线表的专线报价状态
            waybillRouteService.updateQuoteStatus(driverId,waybillId);
            chatServer.onMessage(Constants.webSocket.WAYBILL.toString());
            return CommonResult.success(quote);
        }
        //当前司机已对对该订单报价
        else {
            return CommonResult.failed("请勿重复对同一运单报价");
        }

    }


    /**
     * 货主端（运单1对n）根据订单id查询报价列表（分页查询）
     */
    @PostMapping("shiper/waybillQuotePage")
    public CommonResult<CommonPage<WAGParamVOAndQuote>> waybillQuotePage(@RequestParam Long waybillId,
                                                            @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
                                                            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum){//订单id 司机报价金额
        Waybill waybill = wayBillService.selectById(waybillId);
        //查询针对waybillid的所有报价
        QueryWrapper<Quote> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Quote::getWaybillId,waybillId);
        Page<Quote> quotePage = new Page<>(pageNum, pageSize);
        Page<Quote> page = quoteService.page(quotePage, wrapper);

        Page<WAGParamVOAndQuote> wagParamVOAndQuotePage = quoteService.quotePageToWAGParamVOAndQuotePage(page);
        return CommonResult.success(CommonPage.restPage(wagParamVOAndQuotePage));
    }

    /**
     * 司机端(运单1对1)查询自己的报价列表（分页查询）
     * @param pageSize
     * @param pageNum
     * @return
     */
    @PostMapping("driver/AllQuotePage")
    public CommonResult<CommonPage<WAGParamVOAndQuote>> driverAllQuotePage(@RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
                                                              @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum){
        Long driverId = Long.valueOf(BaseUserInfo.get(UserInfoEnu.id.getCode()));

//        quoteService.getQuo();
        //直接查询driverId对应的quote
        QueryWrapper<Quote> quoteQueryWrapper = new QueryWrapper<>();
        quoteQueryWrapper.lambda().eq(Quote::getDriverId,driverId);

        Page<Quote> quotePage = new Page<>(pageNum, pageSize);
        Page<Quote> page = quoteService.page(quotePage, quoteQueryWrapper);

        Page<WAGParamVOAndQuote> wagParamVOAndQuotePage = quoteService.quotePageToWAGParamVOAndQuotePage(page);


        //根据quote的waybillId查询订单(返回带waybillId的quoteVO)
        return CommonResult.success(CommonPage.restPage(wagParamVOAndQuotePage));
    }


    /**
     * 货主选择其中某一个的报价进行确认
     * @param requestBody
     * @return
     */
    @PostMapping("shiper/chooseQuote")
    @Transactional
    public CommonResult<Map<String,String>> chooseQuote(@RequestBody Map<String,String> requestBody) throws Exception {
//        lock.lock();
        Map<String,String> data = null;
        if (requestBody == null) {
            return CommonResult.failed("请求体不能为空");
        }
        // 使用 Map 的 getOrDefault 方法避免 null
        String code = requestBody.getOrDefault("code", "");

        Long waybillId = getLongFromRequestBody(requestBody, "id");
        Long quoteId = getLongFromRequestBody(requestBody, "qid");

        // 确保 waybillId 和 quoteId 不为 null
        if (waybillId == null || quoteId == null) {
            return CommonResult.failed("请求参数中 id 或 qid 不能为空");
        }
        Waybill waybill = wayBillService.getById(waybillId);
        Short lock = waybill.getWaybillLock();
        if (Constants.WayBillLock.LOCK.equals(lock)) {
            throw new BaseException("请勿重复支付该订单");
        }
//        try {
            //将运单锁定在支付中
            System.out.println("锁定运单");
            waybill.setWaybillLock(Constants.WayBillLock.LOCK);
            wayBillService.updateById(waybill);
            //现付更改报价表
            if (Constants.PayMethod.PAY_NOW.equals(waybill.getPayMethod())) {
                Quote quote = quoteService.getById(quoteId);
                Long cuoId = quote.getCuoId();
                log.info("QuoteCon:"+cuoId);
                CouponDet couponDet = couponDetService.getById(cuoId);
                if (!Objects.isNull(couponDet)) {
//                    CouponDet couponDet = couponDetService.getById(quoteId);
//                couponDet.setUseTime(LocalDateTime.now());
                    Short couLock = couponDet.getCouLock();
                    if (Constants.WayBillLock.LOCK.equals(couLock)) {
                        throw new BaseException("优惠券已被使用");
                    }
                    couponDet.setCouLock(Constants.WayBillLock.LOCK);
                    couponDetService.updateById(couponDet);
//                    quote.setActAmount(quote.getOfferAll().subtract(couponDet.getSum()));
//                    quoteService.updateById(quote);
                }
//                else {
//                    quote.setActAmount(quote.getOfferAll());
//                    quote.setCuoId(null);
//                    quoteService.updateById(quote);
//                }
//                waybill.setPayType(Constants.WayBillPayType.DEPOSIT);

                System.out.println("ActAmount:" + quote.getActAmount());
            }
//            else {
//                waybill.setPayType(Constants.WayBillPayType.DEPOSIT);
//            }
            waybill.setPayType(Constants.WayBillPayType.DEPOSIT);
            wayBillService.updateById(waybill);

            // 金额类型，使用默认值 "deposit" 如果不存在
            String priceType = requestBody.getOrDefault("type", "deposit");

            // 平台类型，使用默认值 "app" 如果不存在
            String platform = requestBody.getOrDefault("platform", "app");
            data = wechatPayService.jsapiAndAppPrepay(code, waybillId, quoteId, priceType, platform);
//        }finally {
//            lock.unlock();
//        }


        waybill.setPayTime(LocalDateTime.now());
        wayBillService.updateById(waybill);

        Long uid = waybill.getShiperId();
        int couponNum = couponDetService.getCouponDetNum(uid);
        User user = userService.getById(uid);
        user.setCouponNum(couponNum);
        userService.updateById(user);
        System.out.println(data);
        chatServer.onMessage(Constants.webSocket.WAYBILL.toString());
        return CommonResult.success(data);
    }
    /**
     * 前端报价列表页：点击确认报价按钮后获取支付订单金额
     */
    @GetMapping("shiper/getPayAmount")
    public CommonResult<BigDecimal> chooseQuote(@RequestParam Long quoteId){
//    public CommonResult<BigDecimal> chooseQuote(@RequestParam Long quoteId , Long couponId){
        Quote quoteDB = quoteService.getById(quoteId);
        Long waybillId = quoteDB.getWaybillId();

            Waybill waybillDB = wayBillService.getById(waybillId);
            short payMethod = waybillDB.getPayMethod();
            BigDecimal PayAmount = new BigDecimal("0");
            if (Constants.PayMethod.PAY_NOW.equals(payMethod)){
                PayAmount = quoteDB.getActAmount();
//                PayAmount = quoteDB.getOfferAll();
            }else {
                PayAmount = quoteDB.getDeposit();
            }
        System.out.println("getPay:"+PayAmount);
        return CommonResult.success(PayAmount);

    }


    /**
     * 司机端修改报价
     */
    @PostMapping("driver/updateQuote")
    public CommonResult<Quote> driverUpdateQuote(@RequestBody Quote quote) {
        if (quote == null) {
            return CommonResult.failed("请求参数不能为空");
        }
        Quote quoteN = quoteService.getById(quote.getId());
        Long waybillId = quoteN.getWaybillId();
        Waybill waybill = wayBillService.getById(waybillId);
        if(Constants.WayBillLock.LOCK.equals(waybill.getWaybillLock())){
            throw new BaseException("货主正在支付中,请勿对报价进行修改");
        }
        if (!Constants.WaybillStatus.AWAIT_QUOTE.equals(waybill.getWaybillStatus())) {
            throw new BaseException("该订单已被下单,无法修改报价");
        }
        // 获取报价
        Long quoteId = quote.getId();
        BigDecimal offerPrice = quote.getOfferPrice();

        Quote quoteDB = quoteService.getById(quoteId);
        if (quoteDB == null) {
            return CommonResult.failed("报价不存在");
        }
        // 判断状态是否是进行中
        if (!Constants.QuoteStatus.IN_PROGRESS.equals(quoteDB.getStatus())) {
            return CommonResult.failed("只有进行中的报价才能修改");
        }
        // 判断报价金额是否小于等于0

        if (Objects.isNull(offerPrice) || offerPrice.compareTo(BigDecimal.ZERO) <= 0){
            return CommonResult.failed("报价不允许为负数或空");
        }
        // 更新报价
        quoteDB.setOfferPrice(offerPrice);
        //计算平台服务费5%
        quoteDB.setOfferInit(CommonUtil.getPlatformServiceFee(quoteDB.getOfferPrice()));
        //开票总金额（含税）= 运费 + 平台服务费
        quoteDB.setOfferAll(quoteDB.getOfferPrice().add(quoteDB.getOfferInit()));

        quoteDB.setActAmount(quoteDB.getOfferAll());
        quoteService.updateById(quoteDB);

        systemMessageService.SendMessageToUpdateQuote(wayBillService.getById(quoteDB.getWaybillId()),quoteDB);

        return CommonResult.success(quoteDB);
    }

    /**
     * 司机端取消报价
     */
    @PostMapping("driver/cancelQuote")
    public CommonResult<String> driverCancelQuote(@RequestBody Long quoteId) {

        if (quoteId == null) {
            return CommonResult.failed("请求参数中 id 不能为空");
        }
        // 获取报价
        Quote quote = quoteService.getById(quoteId);
        if (quote == null) {
            return CommonResult.failed("报价不存在");
        }
        // 判断是否是司机本人
        Long driverId = Long.valueOf(BaseUserInfo.get(UserInfoEnu.id.getCode()));
        if (!quote.getDriverId().equals(driverId)) {
            return CommonResult.failed("只有本人才能取消报价");
        }
        // 判断状态是否是进行中
        if (!Constants.QuoteStatus.IN_PROGRESS.equals(quote.getStatus())) {
            return CommonResult.failed("只有进行中的报价才能取消");
        }
        // 更新状态为已取消
        quote.setStatus(Constants.QuoteStatus.CANCELLED);
        quoteService.updateById(quote);
        return CommonResult.success("取消成功");
    }


    /**
     * 司机端删除报价
     */
    @GetMapping("driver/deleteQuote")
    public CommonResult<String> driverDeleteQuote(@RequestParam Long quoteId) {
        if (quoteId == null) {
            return CommonResult.failed("请求参数中 id 不能为空");
        }
        // 获取报价
        Quote quote = quoteService.getById(quoteId);
        if (quote == null) {
            return CommonResult.failed("报价不存在");
        }
        // 判断是否是司机本人
        Long driverId = Long.valueOf(BaseUserInfo.get(UserInfoEnu.id.getCode()));
        if (!quote.getDriverId().equals(driverId)) {
            throw new BaseException("非专线用户本人操作");
        }

        List<Short> filterList = Arrays.asList(Constants.QuoteStatus.CANCELLED,Constants.QuoteStatus.UNSELECTED,Constants.QuoteStatus.SHIPPER_RETRACTED);
        // 判断状态是否是进行中
        if (filterList.contains(quote.getStatus())) {
            // 删除该报价
            quoteService.removeById(quote);

        }else {
            throw new BaseException("该报价状态不符合要求，不能删除");
        }

        return CommonResult.success("删除成功");
    }

    @GetMapping("getQuote")
    public CommonResult<Object> getQuo(){
        quoteService.getQuo();
        return CommonResult.success("删除成功");
    }

}
